#pragma once

#include "iostream"
#include "vector"
#include "algorithm"

using namespace std;

/*HJJ QQ479287006
 *写一个函数，输入 n ，求斐波那契（Fibonacci）数列的第 n 项（即 F(N)）。斐波那契数列的定义如下：

F(0) = 0,   F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始，之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7（1000000007），如计算初始结果为：1000000008，请返回 1。

 

示例 1：

输入：n = 2
输出：1
示例 2：

输入：n = 5
输出：5

来源：力扣（LeetCode）
链接：https://leetcode.cn/problems/fei-bo-na-qi-shu-lie-lcof
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * */

int fib(int n) {
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;

    return fib(n - 1) + fib(n - 2);
}

int fib(int n) {

    int first = 0;
    int second = 1
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;

    int result = 0;
    while (n-- > 1) {
        result = first + second;
        if (result >= 1000000007) {
            result -= 1000000007;
        }
        first = second;
        second = result;
    }

    return result;
}

int numWays(int n) {
    int first = 1;
    int second = 1;
    if (n == 0)
        return 1;
    if (n == 1)
        return 1;

    int result = 0;
    while (n-- > 1) {
        result = first + second;
        if (result >= 1000000007) {
            result -= 1000000007;
        }
        first = second;
        second = result;
    }

    return result;
}

//动态规划思想菲波那切数列
//1 建立 dp[i]数组 确立下标以及数组结果的定义 这个i 就是 dp[i]的定义为：第i个数的斐波那契数值是dp[i]
//2 确定递推公式 dp[i]的定义为：第i个数的斐波那契数值是dp[i]；
//3 确定初始化值 dp[0] = 0; dp[1] = 1;
//4 确定顺序递归公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出，dp[i]是依赖 dp[i - 1] 和 dp[i - 2]，
// 那么遍历的顺序⼀定是从前到后遍历的

int fib(int N) {
    if (N <= 1) return N;
    vector<int> dp(N + 1);
    dp[0] = 0;
    dp[1] = 1;
    for (int i = 2; i <= N; i++) {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
    return dp[N];
}
//怎么说呢 动态规划不一定是递归也可能是递推 动态规划区分于 贪心 动态规划是可以由前面的推出来的 而贪心直接选择局部最优解就行

